我們一般使用的數字型態不外乎就是int,float,double
但有關金錢的運算就需要更準確的decimal型態了
先來說一下為何不使用double呢?
大家可以試試下面這個例子
// 0.30000000000000004
double a = 0.1 + 0.2;
float,double : 二進制浮點數
decimal : 十進制浮點數
會造成這個原因是因為電腦運算double會轉成二進位去做運算
而小數在二進制很難完整表示,就像我們算1/3一樣
所以我們需要使用更精確的decimal型態來做小數運算
// 0.3
decimal b = 0.1m + 0.2m;
雖然前面說數值運算要用decimal
但有時還是難免會使用到double型態
像是要計算複利時,會呼叫Math.Pow這個double funtion
//1.0221044505936159
double rate = Math.pow(1.3,1.0/12.0);
//1.02210445059362
decimal drate = decimal.Parse(rate.Tostring());
這時發現tostring預設會四捨五入至小數點後14位
因為是在算複利,所以在幾十年後會出現誤差,雖然差值很小但也不容忽視
這時只要給Tostring下G17(double格式)參數就可以保留位數了
MSDN
根據預設,傳回的值只包含 15 個位數的精確度雖然內部維護最多 17 個位數。 如果這個執行個體的值必須大於 15 位數,ToString會傳回PositiveInfinitySymbol或NegativeInfinitySymbol而不是預期的數目。 如果您需要更多有效位數時,指定format"G17"格式規格,它一定會傳回 17 個位數的有效位數或"R",它會傳回 15 位數如果數目可以使用 17 位數來表示,如果只能是數字表示使用最大有效位數。
//1.0221044505936159
decimal drate = decimal.Parse(rate.Tostring("G17"));
這種小數點後10幾位的誤差真的很難發現
但牽扯到金融相關程式
還是必須排除可能的誤差